import java.io.*;
import javax.swing.*;
//import java.awt.event.*;
import java.awt.*;
import java.util.*;
import java.beans.*;
import java.net.*;

public class SupplyChainManagement extends JFrame {
    public static final int WIDTH = 600;
    public static final int HEIGHT = 600;
    public static final int TextFieldW = 40;
    public static final int TextFieldH = 30;
    final static int miniNumPro = 1;
    final static int nonExistance = -1;
    final static int GUIMode = 0;
    public static ArrayList<Product> p = new ArrayList<Product>();
    public static ArrayList<Ingredients> inv = new ArrayList<Ingredients>();
    private static int interfaceMode;
    private static File file = new File("Product.xml");
    private static Container container;

    //private JButton productList, inventoryList;
    //private static JTextArea textArea;

    /*public SupplyChainManagement() {
        super( "Supply Chain Management" );

        container = getContentPane();
        container.setLayout( new FlowLayout() );

        //JMenuBar menuBar;
        JMenu menu, submenu;
        JMenuItem menuItem;

        // set up menu

        JMenuBar menuBar = new JMenuBar();
        setJMenuBar(menuBar);
        menu = new JMenu("Display");
        menuBar.add(menu);

        menuItem = new JMenuItem("Product");
        menu.add(menuItem);

        menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                textArea.setText("");
                displayProduct();
            }
        });
        
        // submenu
        submenu = new JMenu("Inventory");
        menu.add(submenu);

        menuItem = new JMenuItem("Inventory for each product");
        submenu.add(menuItem);

        menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                textArea.setText("");
                displayInventory();
            }
        });

        menuItem = new JMenuItem("Inventory On Hand");
        submenu.add(menuItem);

        menuItem.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent event)
            {
                textArea.setText("");
                currentInv();
            }
        });

        menu = new JMenu("Add");
        menuBar.add(menu);

        menuItem = new JMenuItem("Product");
        menu.add(menuItem);

        menuItem = new JMenuItem("Inventory");
        menu.add(menuItem);

        menu = new JMenu("Produce");
        menuBar.add(menu);

        menu.addActionListener(produceProduct());

        // button
        JButton productList = new JButton( "Product List" );
        container.add( productList );
        JButton inventoryList = new JButton( "Inventory List" );
        container.add( inventoryList );
        JButton invenOnHand = new JButton( "Current Inventory" );
        container.add( invenOnHand );
        JButton addInventory = new JButton("Add Inventory");
        container.add( addInventory );

        // text area
        textArea = new JTextArea(TextFieldH, TextFieldW);
        JScrollPane scrollPane = new JScrollPane(textArea);
        textArea.setEditable(false);
        container.add(scrollPane);

        // add product area
        JButton addProduct = new JButton("Add Product");
        container.add( addProduct );
        //JLabel label1 = new JLabel("Product name:");
        //container.add(label1);
        //JTextField name = new JTextField(20);
        //container.add(name);
        //JLabel label2 = new JLabel("Product quantity:");
        //container.add(label2);
        //JTextField quan = new JTextField(5);
        //container.add(quan);
        //JList pList = new JList(p);

        // produce product
        JButton produceP = new JButton("Produce Product");
        container.add( produceP );

        productList.addActionListener(
            new ActionListener() {
                public void actionPerformed( ActionEvent event )
                {
                    textArea.setText("");
                    displayProduct();
                }
            }
        );

        inventoryList.addActionListener(
            new ActionListener() {
                public void actionPerformed( ActionEvent event )
                {
                    textArea.setText("");
                    displayInventory();
                }
            }
        );

        invenOnHand.addActionListener(
            new ActionListener() {
                public void actionPerformed( ActionEvent event )
                {
                    textArea.setText("");
                    currentInv();
                }
            }
        );

        addProduct.addActionListener(
            new ActionListener() {
                public void actionPerformed( ActionEvent event )
                {
                    textArea.setText("");
                    addProduct();
                }
            }
        );

        addInventory.addActionListener(
            new ActionListener() {
                public void actionPerformed( ActionEvent event ) {
                    textArea.setText("");
                    addInventory();
                } 
            }
        );

        produceP.addActionListener(
            new ActionListener() {
                public void actionPerformed( ActionEvent event ) {
                    textArea.setText("");
                    producePr();
                }
            }
        );

        setSize(WIDTH,HEIGHT);
        setVisible( true );
    }*/

    public static void main(String[] args) {

        System.out.println("input interface:");
        System.out.println("0: GUI interface");
        System.out.println("any key: command line interface");

      	interfaceMode = getNum();
        
        if (!file.exists())
            setProduct();
        else
            readProduct();

        if (interfaceMode == GUIMode)    {
            MainPanel application = new MainPanel();
            //SupplyChainManagement application = new SupplyChainManagement();
            application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
        }

        else {
            displayOption();    // Display a menu of available commands

            int choice = getNum();
            while (choice != 8) {
                switch (choice) {

                    // Add product
                    case 4: {
    			addProduct();
    			break;
                    }

                    // Add inventory
                    case 5: {
                        addInventory();
                        break;
                    }

                    // Display product
                    case 1: {
                        displayProduct();
                        break;
                    }
                    
                    // Display inventory for specific product
                    case 2: {
                        displayInventory();
                        break;
                    }

                    // Display inventory on hand
                    case 3: {
                       currentInv();
                       break;
                    }

                    // Produce product
                    case 6: {
                        break;
                    }

                    // Connect to server
                    case 7: {
                        break;
                    }
                    
                    default: {
                        System.out.println("Invalid Input, Input again");
    			break;
                    }
                }
                displayOption();
    		choice = getNum();

            }
        }
    	/*setProduct();
    	
    	int choice = input();			// Get user input from available commands
		while (choice != 4) {
    		switch (choice) {

    			// Add product
    			case 1: {
    				addProduct();
    				break;
    			}

    			// Display inventory of specific product
    			case 2: {
    				displayInventory();
    				break;
    			}

    			// Display current available inventory
    			case 3: {
    				readInventory();
    				break;
    			}

    			default: {
    				System.out.println("Invalid Input, Input again");
    				break;
    			}
    		}
    		displayOption();
    		choice = input();
 		}*/
   	 }
   	 
   	/* get usr input for main product and inventory */
    private static void setProduct() {
        try{
            FileReader os = new FileReader("config.txt");
            BufferedReader reader = new BufferedReader(os);
            String line = reader.readLine();

            int numProducts = Integer.parseInt(line);
            System.out.print(line);

            for (int i = 0; i < numProducts; ++i) {
                line = reader.readLine();
                StringTokenizer st = new StringTokenizer(line, "\t");
                String pName = st.nextToken();
                int numInventory = Integer.parseInt(st.nextToken());
                p.add(i, new Product(pName, numInventory));
            }

            
            for (int i = 0; i < numProducts; ++i) {
                ArrayList<Ingredients> invTemp = new ArrayList<Ingredients>();
                ArrayList num = new ArrayList();
                for (int j = 0; j < p.get(i).getNumRawMaterial(); ++j) {
                    line = reader.readLine();
                    StringTokenizer st = new StringTokenizer(line, "\t");
                    String invName = st.nextToken();
                    int amountNeeded = Integer.parseInt(st.nextToken());
                    int invOnHand = Integer.parseInt(st.nextToken());

                    // if inventory inputed is in inventory list
                    if (checkDup(invName) != nonExistance) {
                        Ingredients invn = (Ingredients) inv.get(checkDup(invName));
                        invTemp.add(invn);
                        num.add(amountNeeded);
                        //p.get(i).setRawMeterials(invn, amountNeeded);
                    }

                    // if inventory inputed is not in inventory list yet
                    else {
                        if (isInventory(invName) == nonExistance) {	// if inventory inputed is not in product list
                            Inventory temp = new Inventory(invName);
                            temp.setInvOnHand(invOnHand);
                            inv.add(temp);
                            invTemp.add(temp);
                            num.add(amountNeeded);
                            //p.get(i).setRawMeterials(temp, amountNeeded);
                        }

                        else {	// if a product is an inventory
                            Ingredients invn = (Ingredients) p.get(isInventory(invName));
                            invn.setInvOnHand(p.get(isInventory(invName)).getQuantity());
                            invTemp.add(invn);
                            num.add(amountNeeded);
                            //p.get(i).setRawMeterials(invn, amountNeeded);
                            inv.add(invn);
                        }
                    }
                }
                p.get(i).setRawMeterials(invTemp, num);
            }
        } catch (Exception ex) {
            //System.out.println("Finish reading files!");
            ex.printStackTrace();
         }
   }
   	 
    /* check duplicate inventory */
    public static int checkDup(String s) {
    	for (int i = 0; i < inv.size(); ++i) {
    		Ingredients temp = (Ingredients) inv.get(i);
    		if (s.equalsIgnoreCase(temp.getNameProduct())) {
    			return i;
    		}
    	}
    	return -1;
    }
   	
   	/* check if one product is an inventory of another product */
    private static int isInventory(String s) {
    	for (int i = 0; i < p.size(); ++i) {
    		Ingredients temp = (Ingredients) p.get(i);
    		if (s.equalsIgnoreCase(temp.getNameProduct())) {
    			return i;
    		}
    	}
    	return -1;
    }
    
    /* display main menu */
    private static void displayOption() {
    	System.out.println("Avaible options: ") ;
    	System.out.println("Press 1: Display product");
    	System.out.println("Press 2: Display inventory for a specific product: ");
    	System.out.println("Press 3: Display current avaible inventory");
        System.out.println("Press 4: Add product");
        System.out.println("Press 5: Add inventory");
        System.out.println("Press 6: Produce product");
        System.out.println("Press 7: Connect to server");
    	System.out.println("Press 8: Quit program");
    }
   	
   	/* get user input from available option */ 
    /*private static int input() {
    	int temp;
    	Scanner in = new Scanner(System.in);
    	temp=in.nextInt();
    	return temp;
    }*/
    
    /* set quantity for a product */
/*    private static void setQuan(Product a) {
    	System.out.println("Enter quantity: ");
    	int quantity = input();	//number of a product will be produced
    	a.setQuan(quantity);
    }*/
    
    /* allow user add new product */
    public static void addProduct() {
    	//displayProduct();
    	//System.out.println("Choose products: ");
    	//int product = input();
    	//System.out.println (product);	// Test functionality

        ArrayList<Ingredients> invTemp = new ArrayList<Ingredients>();
        ArrayList numNeeded = new ArrayList();

        int quantity;
        int numRM;  // number of raw material
      
        System.out.println("Enter product name: ");
        String name = getString();

        System.out.println("Enter quantity: ");
        quantity = getNum();

        System.out.println("Enter number of raw material: ");
        numRM = getNum();

        Product newProduct = new Product(name, numRM);
        newProduct.setInvOnHand(quantity);

        for (int i = 0; i < numRM; ++i) {
            System.out.println("Enter material name: ");
            String st = getString();    // get name of inventory
            Ingredients tmp = (Ingredients) inv.get(checkDup(st));  // get inventory

            System.out.println("Enter number needed: ");
            int num = getNum();
            invTemp.add(tmp);
            numNeeded.add(num);
            //newProduct.setRawMeterials(tmp, num);
        }

        newProduct.setRawMeterials(invTemp, numNeeded);
    	p.add(newProduct);
    	writeProduct();
    }

    public static void checkOrder(Ingredients temp) {

        if (temp.getInvOnHand() < 0) {
            int NumNeeded = 0 - temp.getInvOnHand();

            if (interfaceMode != GUIMode)
                System.out.println(NumNeeded + " " + temp.getNameProduct() + " was ordered: ");

            else
                JOptionPane.showMessageDialog(null, NumNeeded + " " + temp.getNameProduct() + " was ordered: " + '\n');

            temp.setInvOnHand(NumNeeded);
        }

    }

    /*public static void checkOrder(Product temp) {
        ArrayList invOrdered = new ArrayList();
        ArrayList<Ingredients> rawMaterial = new ArrayList<Ingredients>();

        invOrdered = temp.checkInvenOnHand();
        rawMaterial = temp.getRMaterial();

        for (int i = 0; i < invOrdered.size(); ++i) {
            int index = (Integer) invOrdered.get(i);

            if (interfaceMode != GUIMode)
                System.out.println(rawMaterial.get(index).getInvenOnHand() + rawMaterial.get(index).getName() + "was ordered: ");

            else
                //textArea.append(numNeeded + in.getName() + "was ordered: " + '\n');
                JOptionPane.showMessageDialog(null, rawMaterial.get(index).getInvenOnHand() +
                                              rawMaterial.get(index).getName() + "was ordered: " + '\n' );
        }
    }*/

    private static String getString() {
        Scanner in = new Scanner(System.in);     
	return in.nextLine();
    }

    private static int getNum() {
        Scanner in = new Scanner(System.in);
        return in.nextInt();
    }
    /* allow user add new inventory */
    private static void addInventory() {
        System.out.println("Enter inventory's name:");
        String name = getString();

        Inventory temp = new Inventory(name);

        System.out.println("Enter quantity:");
        int num = getNum();

        temp.setInvOnHand(num);

	inv.add(temp);
        writeProduct();
    }
    
    /* Display inventory for a specific product */
    public static void displayInventory() {
    	/* 1. Display list of products
    	   2. Get input from user
    	   3. Display inventory */

        //if (interfaceMode != GUIMode) {
            for (int i = 0; i < p.size(); ++i) {
                System.out.println(p.get(i).getNameProduct() + ": " + '\n');
                ArrayList<Ingredients> temp = p.get(i).getRawMeterials();
                ArrayList amount = p.get(i).getNumRMNeeded();
                
                for (int j = 0; j < temp.size(); ++j) {
                    System.out.println("   " + temp.get(j).getNameProduct() + ": " + amount.get(j) + '\n');
                }
                System.out.println(" " + '\n');
            }
        //}

       /* else {
            for (int i = 0; i < p.size(); ++i) {
                textArea.append(p.get(i).getNameProduct() + ": " + '\n');
                ArrayList<Ingredients> temp = p.get(i).getRawMeterials();
                ArrayList amount = p.get(i).getNumRMNeeded();

                for (int j = 0; j < temp.size(); ++j) {
                    textArea.append("   " + temp.get(j).getNameProduct() + ": " + amount.get(j) + '\n');
                }
                textArea.append(" " + '\n');
            }
        }*/
    }
    
    /* Display a list of product */
    public static void displayProduct() {        
        System.out.println("List of products: ");
        for (int i = 0; i < p.size(); ++i)
            System.out.println((i+1) + ". " + p.get(i).getNameProduct() + '\n');
    }
    
    /* write current avaible inventory from a file */
    public static void writeProduct() {
    	try {
            XMLEncoder encoder = new XMLEncoder(
                new BufferedOutputStream (new FileOutputStream ( file )));

            encoder.writeObject(p.size());

            for (int i = 0; i < p.size(); ++i) {
                encoder.writeObject(p.get(i));

                ArrayList<Ingredients> invTemp = new ArrayList<Ingredients>();
                ArrayList num = new ArrayList();
                invTemp = p.get(i).getRawMeterials();
                num = p.get(i).getNumRMNeeded();

                for (int j = 0; j < p.get(i).getNumRawMaterial(); ++j) {
                    
                    encoder.writeObject(invTemp.get(j));
                    //System.out.println(invTemp.get(j).getNameProduct());
                    encoder.writeObject(num.get(j));
                }
            }
            for (int i = 0; i < inv.size(); ++i) {
                boolean isIn = false;
                for (int j = 0; j < p.size(); ++j) {
                    ArrayList<Ingredients> temp = new ArrayList<Ingredients>();
                    temp = p.get(j).getRawMeterials();
                    //boolean isIn = falseboolean ;

                    for(int k = 0; k < temp.size(); ++k) {
                        if (inv.get(i).equals(temp.get(k))) {
                           isIn = true;
                           break;
                        }
                    }

                    if(isIn)
                        break;
                }
                
                if(isIn == false) {
                        System.out.println(inv.get(i).getNameProduct());
                        encoder.writeObject(inv.get(i));
                    }
            }
               
            encoder.close();
    	} catch (IOException ex) {
    		ex.printStackTrace();
    	}
    	
    }
    
    /* read current avaible inventory from a file */
    private static void readProduct() {
    	try {
            XMLDecoder decoder = new XMLDecoder (
                    new BufferedInputStream ( new FileInputStream ( file )  )  ) ;

            int numProduct = (Integer) decoder.readObject () ;

            for (int i = 0; i < numProduct; ++i) {
                Product temp = (Product) decoder.readObject ();

                p.add(i, temp);

                ArrayList<Ingredients> invn = new ArrayList<Ingredients>();
                ArrayList num = new ArrayList();
                //System.out.println(p.get(i).getNameProduct()+ ": " + p.get(i).getNumRawMaterial());

                for (int j = 0; j < p.get(i).getNumRawMaterial(); ++j) {
                    Ingredients ingd = (Ingredients) decoder.readObject();

                    if (checkDup(ingd.getNameProduct()) == nonExistance) {
                        inv.add(ingd);
                        invn.add(ingd);
                    }

                    else
                        invn.add((Ingredients) inv.get(checkDup(ingd.getNameProduct())));
                    //System.out.println(invn.get(j).getNameProduct() + ": " + invn.get(j).getInvOnHand());

                    num.add((Integer) decoder.readObject());
                    //System.out.println("Num needed: " + num.get(j));
                }
                p.get(i).setRawMeterials(invn, num);
                //System.out.println(p.get(i).getRawMeterials().size());
            }

            while (true) {
                Ingredients temp = (Ingredients) decoder.readObject ();

                if (temp == null)
                    break;
                // if inventory is not in inventory list
                //System.out.println(temp.toString());
                if (checkDup(temp.getNameProduct()) == nonExistance) {
                    inv.add(temp);
                }

            }
    	} 
        catch(Exception end) {
            System.out.println("end of file");
    	}

       // catch (ArrayIndexOutOfBoundsException exception) {
       //     exception.printStackTrace();
       // }
    }

    /* display current inventory */
    public static void currentInv() {      
        for (int i = 0; i < inv.size(); ++i) {
            int num = inv.get(i).getInvOnHand();
            if (num >= 0) {
                System.out.println(inv.get(i).getNameProduct() + ": " + num + '\n');
            }
        }
    }

    private static void createServer() {
        try {
            ServerSocket server = new ServerSocket(8006);
            while (true) {
            System.out.print("Start!");
            Socket connection = server.accept();
            BufferedReader in = new BufferedReader( new InputStreamReader (connection.getInputStream()));
            while (true) {
                String str = in.readLine();
                if (str.equalsIgnoreCase("terminate")) {
                    break;
                }
                else {
                    System.out.println(str);
                }
            }

            }
        } catch(Exception e) {
            //e.printStackTrace();
            System.out.println("Connection Close!");
        }
    }

/*    private static void producePr() {
        if (interfaceMode != GUIMode) {

        }

        else {
            JComboBox comboBox = new JComboBox();
            comboBox.setMaximumRowCount( p.size() );

            // handle JComboBox event
            comboBox.addItemListener(
                new ItemListener() {
                    public void itemStateChanged( ItemEvent event ) {
                        if ( event.getStateChange() == ItemEvent.SELECTED ) {

                        }

                    }
                }
            );

            container.add(comboBox);
        }
    }

    ActionListener produceProduct() {
        return new produceHandler();
    }
    
    class produceHandler implements ActionListener {
        JDialog dialog;
        public void actionPerformed (ActionEvent evt) {
            if (dialog == null) {
                dialog = new ProduceDialog(SupplyChainManagement.this);
            }
            dialog.show();
        }
    }*/

}


